using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using NuoYan.Extension;
using System;
using NPOI.SS.Formula.Functions;

namespace NuoYan.Excel
{
	[ExcelAsset]
	/// <summary>
	/// 用于制作拓展功能基类
	/// </summary>
	public abstract class ReadExcelDataBaseSO : ScriptableObject, IReadOnlyDictionary<string, ItemDataBase>, IList<KeyValuePair<string, ItemDataBase>>
	{
		/// <summary>
		/// 数据缓存字典
		/// </summary>
		protected Dictionary<string, ItemDataBase> ItemDataDic = new Dictionary<string, ItemDataBase>();
		/// <summary>
		/// 数据缓存列表（有序）
		/// </summary>
		protected List<KeyValuePair<string, ItemDataBase>> ItemDataList = new List<KeyValuePair<string, ItemDataBase>>();
		[ReadInEditor]
		public string excelFilePath;
		[ContextMenu("Set Flages")]
		public void SetFlages()
		{
			hideFlags = HideFlags.None;
		}
		[ContextMenu("Hide Flages")]
		public void HideFlages()
		{
			hideFlags = HideFlags.NotEditable;
		}
		public virtual void Init()
		{
			Debug.Log($"----------------{this.name}表格数据初始化完成-------------------".ColorString(Color.green));
		}
		/// <summary>
		/// 单个数据加入
		/// </summary>
		/// <param name="key"></param>
		/// <param name="data"></param>
		public void AddData(string key, ItemDataBase data)
		{
			if (ItemDataDic.ContainsKey(key))
			{
				// 更新字典和列表
				ItemDataDic[key] = data;
				int idx = ItemDataList.FindIndex(kv => kv.Key == key);
				if (idx >= 0)
					ItemDataList[idx] = new KeyValuePair<string, ItemDataBase>(key, data);
			}
			else
			{
				ItemDataDic.Add(key, data);
				ItemDataList.Add(new KeyValuePair<string, ItemDataBase>(key, data));
			}
		}
		/// <summary>
		/// 一组数据加入
		/// </summary>
		/// <param name="datas"></param>
		public void AddData<T>(List<T> datas)
		{
			foreach (var data in datas)
			{
				if (data is ItemDataBase itemData)
				{
					AddData(itemData.ItemID, itemData);
				}
			}
		}
		/// <summary>
		/// 一组数据加入
		/// </summary>
		/// <param name="datas"></param>
		public void AddData<T>(T[] datas)
		{
			foreach (T data in datas)
			{
				if (data is ItemDataBase itemData)
				{
					AddData(itemData.ItemID, itemData);
				}
			}
		}
		/// <summary>
		/// 获得数据，通过此方法获得的数据为源数据，请勿轻易修改
		/// </summary>
		/// <param name="key"></param>
		/// <returns>指定源数据</returns>
		public ItemDataBase GetData(string key)
		{
			if (string.IsNullOrEmpty(key)) return null;
			if (ItemDataDic.ContainsKey(key))
			{
				return ItemDataDic[key];
			}
			else
			{
				Debug.LogError($"没有找到key为<{key}>的数据");
				return null;
			}
		}
		/// <summary>
		/// 获得数据，通过此方法获得的数据为源数据，请勿轻易修改
		/// </summary>
		/// <param name="key"></param>
		/// <returns>指定源数据</returns>
		public T GetData<T>(string key) where T : ItemDataBase
		{
			return GetData(key) as T;
		}
		/// <summary>
		/// 获得数据，通过此方法获得的数据为源数据，请勿轻易修改
		/// </summary>
		/// <param name="key"></param>
		/// <returns>指定源数据</returns>
		public T GetData<T>(Predicate<T> condition) where T : ItemDataBase
		{
			if (condition == null)
			{
				Debug.LogWarning("条件不可为空");
			}
			T result = default;
			foreach (var item in ItemDataDic.Values)
			{
				if (item is T t && condition(t))
				{
					result = t;
					break;
				}
			}
			return result;
		}
		/// <summary>
		/// 获得数据，通过此方法获得的数据为源数据，请勿轻易修改
		/// </summary>
		/// <param name="key"></param>
		/// <returns>指定源数据</returns>
		public T[] GetDatas<T>(Predicate<T> condition) where T : ItemDataBase
		{
			if (condition == null)
			{
				Debug.LogWarning("条件不可为空");
				return null;
			}
			var datas = new List<T>();
			foreach (var item in ItemDataDic.Values)
			{
				if (item is T t && condition(t))
					datas.Add(t);
			}
			return datas.ToArray();
		}

		public bool RemoveByKey(string key)
		{
			if (ItemDataDic.ContainsKey(key))
			{
				ItemDataDic.Remove(key);
				int idx = ItemDataList.FindIndex(kv => kv.Key == key);
				if (idx >= 0)
					ItemDataList.RemoveAt(idx);
				return true;
			}
			else
			{
				Debug.LogError($"没有找到key为<{key}>的数据");
				return false;
			}
		}
		public bool RemoveByValue(ItemDataBase data)
		{
			return RemoveByKey(data.ItemID);
		}
		public int Count => ItemDataList.Count;
		public IEnumerable<string> Keys => ItemDataList.Select(kv => kv.Key);
		public IEnumerable<ItemDataBase> Values => ItemDataList.Select(kv => kv.Value);

		public int IndexOfKey(string key)
		{
			var list = ItemDataDic.Keys.ToList();
			return list.IndexOf(key);
		}

		public int IndexOfValue(ItemDataBase value)
		{
			var list = ItemDataDic.Values.ToList();
			return list.IndexOf(value);
		}
		public void LogAll()
		{
			foreach (var item in ItemDataDic)
			{
				Debug.Log(item.Key + "  " + item.Value);
			}
		}
		public bool ContainsKey(string key)
		{
			return ItemDataDic.ContainsKey(key);
		}
		public bool ContainsValue(ItemDataBase value)
		{
			return ItemDataDic.ContainsValue(value);
		}

		public IEnumerator<KeyValuePair<string, ItemDataBase>> GetEnumerator()
		{
			foreach (var item in ItemDataDic)
			{
				yield return item;
			}
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
		public void Clear()
		{
			ItemDataDic.Clear();
			ItemDataList.Clear();
		}

		public bool TryGetValue(string key, out ItemDataBase value)
		{
			if (string.IsNullOrEmpty(key))
			{
				value = null;
				return false;
			}
			if (ItemDataDic.TryGetValue(key, out value))
				return true;
			value = null;
			return false;
		}

		/// <summary>
		/// 获得数据，通过此方法获得的数据为源数据，请勿轻易修改
		/// </summary>
		/// <param name="key"></param>
		/// <returns>指定源数据</returns>
		public ItemDataBase this[string key]
		{
			get { return GetData(key); }
			set { AddData(key, value); }
		}

		#region 有序
		public bool IsReadOnly => false;
		/// <summary>
		/// 获得数据，通过此方法获得的数据为源数据，请勿轻易修改
		/// </summary>
		/// <param name="key"></param>
		/// <returns>指定源数据</returns>
		public KeyValuePair<string, ItemDataBase> this[int index]
		{
			get => ItemDataList[index];
			set
			{
				var oldKey = ItemDataList[index].Key;
				ItemDataList[index] = value;
				if (ItemDataDic.ContainsKey(oldKey))
					ItemDataDic.Remove(oldKey);
				ItemDataDic[value.Key] = value.Value;
			}
		}

		public int IndexOf(KeyValuePair<string, ItemDataBase> item)
		{
			return ItemDataList.IndexOf(item);
		}

		public void Insert(int index, KeyValuePair<string, ItemDataBase> item)
		{
			ItemDataList.Insert(index, item);
			ItemDataDic[item.Key] = item.Value;
		}

		public void RemoveAt(int index)
		{
			var key = ItemDataList[index].Key;
			ItemDataList.RemoveAt(index);
			ItemDataDic.Remove(key);
		}

		public void Add(KeyValuePair<string, ItemDataBase> item)
		{
			if (!ItemDataDic.ContainsKey(item.Key))
			{
				ItemDataList.Add(item);
				ItemDataDic.Add(item.Key, item.Value);
			}
			else
			{
				// 若已存在则更新
				AddData(item.Key, item.Value);
			}
		}

		public bool Contains(KeyValuePair<string, ItemDataBase> item)
		{
			return ItemDataList.Contains(item);
		}

		public void CopyTo(KeyValuePair<string, ItemDataBase>[] array, int arrayIndex)
		{
			ItemDataList.CopyTo(array, arrayIndex);
		}

		public bool Remove(KeyValuePair<string, ItemDataBase> item)
		{
			if (ItemDataList.Remove(item))
			{
				ItemDataDic.Remove(item.Key);
				return true;
			}
			return false;
		}
		#endregion
	}
}


